<template>
  <base-table-header-tools></base-table-header-tools>
  <el-table
    :data="
      tableData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
    "
    :default-sort="defaultSort"
    @selection-change="selectChange"
    @sort-change="sortChange"
    stripe
  >
    <!-- 选择框 -->
    <el-table-column type="selection" width="55" fixed></el-table-column>
    <!-- 序号 -->
    <el-table-column type="index" label="序号" width="60"></el-table-column>
    <!-- 数据列 -->
    <template v-for="(tableField, key) in props.tableFieldList" :key="key">
      <el-table-column
        :prop="tableField.filedName"
        :label="tableField.label"
        :width="tableField.width"
        :min-width="tableField.minWidth"
        :formatter="dataFormat"
        sortable="custom"
        fit
      >
      </el-table-column>
    </template>
    <el-table-column label="操作" :width="fixedFuncBtn.width" fixed="right" fit>
      <template #default="scope">
        <el-button
          type="text"
          size="small"
          icon="edit"
          @click.prevent="
            setSubmitFunctionType('update');
            setFormInitValue(scope.row);
            changeSubmitFormDialogVisible();
          "
          >编辑
        </el-button>
        <template v-if="props.detailBtnVisible">
          <el-button
            type="text"
            size="small"
            icon="ChatLineSquare"
            @click.prevent="
              setSubmitFunctionType('detail');
              setFormInitValue(scope.row);
              changeDetailFormDialogVisibleValue();
            "
            >详情
          </el-button>
        </template>

        <template v-for="(btn, index) in fixedFuncBtn.button" :key="index">
          <el-button
            size="small"
            @click="btn.method(scope.row)"
            :icon="btn.icon"
            :type="btn.type"
            >{{ btn.name }}
          </el-button>
        </template>
      </template>
    </el-table-column>
  </el-table>
  <div class="table-suffix-tool">
    <el-pagination
      style="float: right"
      layout="total, sizes, prev, pager, next, jumper"
      :total="tableData.length"
      :page-sizes="[5, 10, 15, 20, 50]"
      :default-page-size="pageSize"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    ></el-pagination>
  </div>
  <base-submit-form-dialog v-model="submitFormDialogVisible">
    <template #submitDialogSlot>
      <slot name="submitForm"></slot>
    </template>
  </base-submit-form-dialog>
  <upload-dialog
    v-model="uploadDialogVisible"
    @submit-json-format="submitJsonFormat"
  >
    <template #uploadDialogSlot>
      <slot name="uploadDialogContent"></slot>
    </template>
  </upload-dialog>
  <detail-form-dialog v-model="detailFormDialogVisible">
    <template #detailFormDialogSlot>
      <slot name="detailFormDialog"></slot>
    </template>
  </detail-form-dialog>
</template>

<script lang="ts" setup>
import {
  withDefaults,
  defineProps,
  defineEmits,
  provide,
  defineExpose,
} from "vue";

import { FixedFuncBtn, TableField, TableUrl } from "@/models/TableSetting";

import TableData from "@/components/table/basic/TableData";
import BaseTableHeaderTools from "@/components/table/basic/BaseTableHeaderTools.vue";
import BaseSubmitFormDialog from "@/components/table/basic/BaseSubmitFormDialog.vue";
import BaseSubmitForm from "@/components/table/basic/BaseSubmitForm";
import Pagination from "@/components/table/basic/Pagination";
import TableSort from "@/components/table/basic/TableSort";
import TableDelete from "@/components/table/basic/TableDelete";
import UploadDialog from "@/components/table/basic/UploadDialog.vue";
import UploadDialogEvent from "@/components/table/basic/UploadDialog";
import DetailFormDialog from "@/components/table/basic/DetailFormDialog.vue";
import DetailForm from "@/components/table/basic/DetailForm";

export interface BaseTableProp {
  url: TableUrl;
  tableFieldList: Array<TableField>;
  submitForm: Record<string, unknown>;
  submitFormWidth?: string;
  submitFormTitle?: string;
  fixedFuncBtn?: FixedFuncBtn;
  detailBtnVisible?: boolean;
  detailFormDialog?: {
    title: string;
    width: string;
  };
}

const props = withDefaults(defineProps<BaseTableProp>(), {
  url: () => {
    return {
      refreshUrl: "",
      modifyingSingleUrl: "",
      modifyingBatchUrl: "",
      deleteUrl: "",
    } as TableUrl;
  },
  tableFieldList: () => {
    return {} as Array<TableField>;
  },
  submitForm: () => {
    return {};
  },
  submitFormWidth: "50%",
  submitFormTitle: "测试",
  fixedFuncBtn: () => {
    return { width: 120, button: [] } as FixedFuncBtn;
  },
  detailBtnVisible: false,
  detailFormDialog: () => {
    return {
      title: "单据详情",
      width: "50%",
    };
  },
});
provide("props", props);

const emit = defineEmits<{
  (
    e: "data-format",
    columnName: string,
    cellValue: string,
    callback: (value: string) => void
  ): void;
  (
    e: "set-form-init-value",
    formType: string,
    row: Record<string, unknown>
  ): void;
  (e: "submit-valid", callback: (value: boolean) => void): void;
  (
    e: "json-format",
    data: Record<string, unknown>[][],
    callback: (value: Record<string, unknown>[]) => void
  ): void;
}>();

// 表格数据、 表格数据获取方法、 表格数据规范化、 基本搜索.
const { tableData, getRecord, dataFormat } = TableData(props, emit);
// 获取数据
getRecord(props.url.refreshUrl);

// 表格分页
const { pageSize, currentPage, handleSizeChange, handleCurrentChange } =
  Pagination();

// 表排序
const { defaultSort, sortChange } = TableSort(tableData);

// 数据新增、编辑.
const {
  submitFormDialogVisible,
  changeSubmitFormDialogVisible,
  setSubmitFunctionType,
  setFormInitValue,
} = BaseSubmitForm(props, emit, getRecord);

/**
 * 详情窗口
 */
const { detailFormDialogVisible, changeDetailFormDialogVisibleValue } =
  DetailForm();

// 批量删除
const { selectChange } = TableDelete(props, getRecord);

// 引入上传所用到的事件和方法
const { uploadDialogVisible } = UploadDialogEvent();

const submitJsonFormat = (
  data: Record<string, unknown>[][],
  callback: (value: Record<string, unknown>[]) => void
) => {
  let newValue: Record<string, unknown>[] = [];
  emit("json-format", data, (value: Record<string, unknown>[]) => {
    newValue = value;
  });
  callback(newValue);
};

/**
 * 暴露数据给父组件
 */
defineExpose({
  tableData,
});
</script>

<style scoped>
.table-suffix-tool {
  background: #ffffff;
  height: 50px;
  width: 100%;
  padding-top: 10px;
}
</style>
